x86: Add a new physdev_op PHYSDEVOP_setup_gsi for GSI setup.
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 24 Nov 2009 14:43:07 +0000 (14:43 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 24 Nov 2009 14:43:07 +0000 (14:43 +0000)
GSI 0-15 is setup by hypervisor, and GSI > =16 is setup by dom0
this physdev_op PHYSDEVOP_setup_gsi. This patch can help dom0
to get rid of intrusive changes of ioapic.

Signed-off-by: Xiantao Zhang <xiantao.zhang@intel.com>
xen/arch/x86/mpparse.c
xen/arch/x86/physdev.c
xen/include/public/physdev.h

index 33648562ae50b0f92613fa7a30cc4ffef678c557..fae08764d855b60388f17e09aa2cce3f35cf702c 100644 (file)
@@ -1122,7 +1122,7 @@ int mp_register_gsi (u32 gsi, int triggering, int polarity)
        ioapic = mp_find_ioapic(gsi);
        if (ioapic < 0) {
                printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
-               return gsi;
+               return -EINVAL;
        }
 
        ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
@@ -1141,12 +1141,12 @@ int mp_register_gsi (u32 gsi, int triggering, int polarity)
                printk(KERN_ERR "Invalid reference to IOAPIC pin "
                        "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
                        ioapic_pin);
-               return gsi;
+               return -EINVAL;
        }
        if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
                Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
                        mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
-               return gsi_to_irq[gsi];
+               return -EEXIST;
        }
 
        mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
@@ -1180,14 +1180,13 @@ int mp_register_gsi (u32 gsi, int triggering, int polarity)
                        gsi_to_irq[irq] = gsi;
                } else {
                        printk(KERN_ERR "GSI %u is too high\n", gsi);
-                       return gsi;
+                       return -E2BIG;
                }
        }
 
-       io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+       return io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
                    triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
                    polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
-       return gsi;
 }
 
 #endif /* CONFIG_X86_IO_APIC */
index 2d65fa4df435ab10e07139688d860be0de8ee34f..b0d777a6e8daa4c3e558e7ca57a35b116b836db6 100644 (file)
@@ -62,13 +62,18 @@ static int physdev_map_pirq(struct physdev_map_pirq *map)
                 ret = -EINVAL;
                 goto free_domain;
             }
+
             irq = domain_pirq_to_irq(current->domain, map->index);
             if ( !irq )
             {
-                dprintk(XENLOG_G_ERR, "dom%d: map pirq with incorrect irq!\n",
-                        d->domain_id);
-                ret = -EINVAL;
-                goto free_domain;
+                if ( IS_PRIV(current->domain) )
+                    irq = map->index;
+                else {
+                    dprintk(XENLOG_G_ERR, "dom%d: map pirq with incorrect irq!\n",
+                            d->domain_id);
+                    ret = -EINVAL;
+                    goto free_domain;
+                }
             }
             break;
 
@@ -457,6 +462,28 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
         spin_unlock(&pcidevs_lock);
         break;
     }
+    case PHYSDEVOP_setup_gsi: {
+        struct physdev_setup_gsi setup_gsi;
+
+        ret = -EPERM;
+        if ( !IS_PRIV(v->domain) )
+            break;
+
+        ret = -EFAULT;
+        if ( copy_from_guest(&setup_gsi, arg, 1) != 0 )
+            break;
+        
+        ret = -EINVAL;
+        if ( setup_gsi.gsi < 0 || setup_gsi.gsi >= nr_irqs_gsi )
+            break;
+        /* GSI < 16 has been setup by hypervisor */
+        if ( setup_gsi.gsi >= 16 )
+            ret = mp_register_gsi(setup_gsi.gsi, setup_gsi.triggering,
+                            setup_gsi.polarity);
+        else 
+            ret = -EEXIST;
+        break; 
+    }
     default:
         ret = -ENOSYS;
         break;
index 29374024e158edbb9107f44fd07e5c365d5bf0e6..18d30593c6218e98c9fbed71ac1c21576fb89be9 100644 (file)
@@ -227,6 +227,19 @@ struct physdev_op {
 typedef struct physdev_op physdev_op_t;
 DEFINE_XEN_GUEST_HANDLE(physdev_op_t);
 
+#define PHYSDEVOP_setup_gsi    21
+struct physdev_setup_gsi {
+    int gsi;
+    /* IN */
+    uint8_t triggering;
+    /* IN */
+    uint8_t polarity;
+    /* IN */
+};
+
+typedef struct physdev_setup_gsi physdev_setup_gsi_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_setup_gsi_t);
+
 /*
  * Notify that some PIRQ-bound event channels have been unmasked.
  * ** This command is obsolete since interface version 0x00030202 and is **